use super::sqlite_r2d2::{SqliteConnectionManager};
use cross_rs::IResult;
use rusqlite::{params, OptionalExtension};
use std::sync::Arc;
use tokio::task;
use redis_rs::Pool;

#[derive(Debug)]
struct User {
    id: i64,
    name: String,
    balance: i64,
}

pub async fn main_run() -> IResult {
    // 创建SQLite连接池 (启用WAL模式)
    let manager = SqliteConnectionManager::file("concurrent.db")
        .with_init(|conn| {
            // 启用WAL模式(写并发优化)
            conn.pragma_update(None, "journal_mode", "WAL")?;
            // 提高busy_timeout减少锁冲突
            conn.pragma_update(None, "busy_timeout", 5000)?;
            Ok(())
        });
    // 避免频繁创建连接
    // 控制最大连接数防止资源耗尽
    let pool = Pool::builder().max_size(20).build(manager)?;
    let pool = Arc::new(pool);
    
    // 初始化数据库
    init_db(&pool)?;
    
    // 创建线程池 (控制并发数)
    let rt = tokio::runtime::Builder::new_multi_thread()
        .worker_threads(8)
        .enable_all()
        .build()?;
    
    // 并发更新任务 (100个并发转账)
    let mut handles = vec![];
    for i in 0..100 {
        let pool = pool.clone();
        handles.push(rt.spawn(async move {
            transfer_funds(&pool, 1, 2, 1).await
        }));
    }
    
    // 等待所有任务完成
    for handle in handles {
        handle.await?;
    }
    
    // 验证最终余额
    let final_balance = get_balance(&pool, 1).await?;
    println!("最终余额: {}", final_balance);
    
    Ok(())
}

fn init_db(pool: &Pool<SqliteConnectionManager>) -> IResult {
    let conn = pool.get()?;
    conn.execute_batch(
        "BEGIN;
        DROP TABLE IF EXISTS users;
        CREATE TABLE users (
            id INTEGER PRIMARY KEY,
            name TEXT NOT NULL,
            balance INTEGER NOT NULL
        );
        INSERT INTO users (name, balance) VALUES ('Alice', 100);
        INSERT INTO users (name, balance) VALUES ('Bob', 50);
        COMMIT;",
    )?;
    Ok(())
}

async fn transfer_funds(
    pool: &Pool<SqliteConnectionManager>,
    from: i64,
    to: i64,
    amount: i64
) -> IResult {
    let pool = pool.clone();
    task::spawn_blocking(move || {
        let mut conn = pool.get()?;
        // 确保转账操作的原子性
        // 减少事务提交次数提高性能
        let tx = conn.transaction()?;  // 显式事务
        
        // 检查余额是否充足
        let balance: i64 = tx.query_row(
            "SELECT balance FROM users WHERE id = ?",
            params![from],
            |row| row.get(0)
        )?;
        
        if balance < amount {
            return Err("余额不足".into());
        }
        
        // 扣减转出账户
        tx.execute(
            "UPDATE users SET balance = balance - ? WHERE id = ?",
            params![amount, from]
        )?;
        
        // 增加转入账户
        tx.execute(
            "UPDATE users SET balance = balance + ? WHERE id = ?",
            params![amount, to]
        )?;
        
        tx.commit()?;
        Ok(())
    }).await?
}

async fn get_balance(
    pool: &Pool<SqliteConnectionManager>,
    user_id: i64
) -> IResult<i64> {
    let pool = pool.clone();
    let result = task::spawn_blocking(move || -> Result<i64, Box<dyn std::error::Error + Send + Sync>> {
        let conn = pool.get()?;
        let balance = conn.query_row("SELECT balance FROM users WHERE id = ?", params![user_id], |row| row.get(0))?;
        Ok(balance)
    }).await?;
    result
}